using System;
using System.Drawing;
using System.Windows.Forms;

using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Document;

using Notepad_X.Classes;
using Notepad_X.Components;
using Notepad_X.Plugin;

namespace Notepad_X
{
   /*This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http:www.gnu.org/licenses/>. */

    public partial class Main : Form
    {
        #region Public Variables

        static public string System_SHEMEFOLDER;
        static public string System_ROOT;
        static public string System_CONFIGFILE;

        public string System_AppData_FOLDER;

        public DocumentsCollection Documents = new DocumentsCollection();
        /// <summary>
        /// Application Settings , type of Settings Class
        /// </summary>
        public static Settings app_settings;

        /// <summary>
        /// Application Language , type of Language Class
        /// </summary>
        public static Language app_language;

        public Options Options_Dialog;
        public About About_Dialog;
        public Favourites Favourites_Dialog;

        public static int Version = 2300;
        public static string VersionName = "2.3";

        public static Boolean LiteVersion
        {
            get { return app_settings.LiteVersion; }
            set { app_settings.LiteVersion = value; }
        }
        public Boolean useAppDataFolder = false;

        public delegate void LoadFileDelegate();

        public delegate void DocumentEventHandler(Classes.Event.DocumentEvent e);

        public event DocumentEventHandler DocumentEvent;

   
        #endregion

        #region Private Variables

        /// <summary>
        /// Variables required for the tab control
        /// </summary>
        int selectedTabIndex = -1;
        bool selectedTabContext = false;
        Color Background_Color = SystemColors.Window, Text_Color = SystemColors.WindowText;
        //private int defaultEditorIndex = 0;
       // public int DefaulEditorIndex { get { return defaultEditorIndex; } set { defaultEditorIndex = value; } }
        #endregion

        #region ProcessParameters
        public string[] Args;
        public delegate void ProcessParametersDelegate(object sender, string[] args);

        public void ProcessParameters(object sender, string[] args)
        {
            this.BringToFront();

            if (args != null && args.Length != 0)
            {
                for (int i = 0; i < args.Length; i++)
                {
                    if (!args[i].StartsWith("/"))
                    {
                        if (System.IO.File.Exists(args[i]))
                        {
                            system_open(args[i]);
                        }
                    }
                    else
                    {
                        string command = args[i].Substring(1);
                        EventHandler handler = Notepad_X.Classes.Event.Events.AddHandler(command);
                        if (handler != null) handler.Invoke(null, null);
                      
                    }
                }
            }
        }
        #endregion

        /// <summary>
        /// Default constructor for Main form
        /// </summary>
        public Main()
        {
            Notepad_X.Static.MainInstance = this;

            InitializeComponent();

            app_settings = new Settings();
            app_language = new Language();

            //Create menu items for selecting tabs
            for (int i = 0; i < 10; i++)
            {
                ToolStripMenuItem item = new ToolStripMenuItem();
                item.Text = "Tab " + (i + 1);
                item.Tag = i;
                item.Name = "Tabs_Select_" + i;
                Menu_Tabs.DropDownItems.Add(item);
                item.Click += new EventHandler(SelectTab_item_Click);
                item.Visible = false;
            }

            DocumentEvent += new DocumentEventHandler(Main_DocumentEvent);
        }

        /// <summary>
        /// Menu item click handler for selecting tabs
        /// </summary>
        void SelectTab_item_Click(object sender, EventArgs e)
        {
            int id = int.Parse(((ToolStripMenuItem)sender).Tag.ToString());
            if (Panel.TabCount >= id)
            {
                Panel.SelectedIndex = id;
            }
        }
        private void Main_Load(object sender, EventArgs e)
        {
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            DocumentTypes.AddType(typeof(ICshartDocument));
            DocumentTypes.Added += new EventHandler(DocumentTypes_Added);
    

            this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
            this.Text = "Notepad X v2";
            System_ROOT = Application.StartupPath;

            //Add the required items to the IconsCollection
            IconsCollection.Images.Add("documentok", Notepad_X.Properties.Resources.page_green);
            IconsCollection.Images.Add("documentchanged", Notepad_X.Properties.Resources.page_red);

            //Set the dialogs
            Options_Dialog = new Options();
            About_Dialog = new About();
            Favourites_Dialog = new Favourites();

            //Set default language strings
            app_language.set_default();

            //Set default settings
            app_settings.set_default();
            app_settings.setFavouritesMenu(Menu_Tools_Favourites);

            System_CONFIGFILE = Main.System_ROOT + "\\Config.xml";
            try{
                if (System.IO.File.Exists(System_CONFIGFILE)){
                    System.IO.FileStream fs = new System.IO.FileStream(System_CONFIGFILE, System.IO.FileMode.Open);
                    if (!fs.CanWrite) new Exception();

                    fs.Close();
                }
            }catch (Exception){
                System_AppData_FOLDER = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Notepad X";

                if (!System.IO.Directory.Exists(System_AppData_FOLDER)) System.IO.Directory.CreateDirectory(System_AppData_FOLDER);

                if (!System.IO.Directory.Exists(System_AppData_FOLDER + "\\Highlighters\\")) System.IO.Directory.CreateDirectory(System_AppData_FOLDER + "\\Highlighters\\");
               
                System_CONFIGFILE = System_AppData_FOLDER + "\\Config.xml";

                useAppDataFolder = true;
            }
            System_SHEMEFOLDER = Application.StartupPath + "\\Highlighters\\";
            if (!System.IO.Directory.Exists(System_SHEMEFOLDER))
            {
                if(!useAppDataFolder)System.IO.Directory.CreateDirectory(System_SHEMEFOLDER);
            }
            
            HighlightingManager.Manager.AddSyntaxModeFileProvider(new FileSyntaxModeProvider(System_SHEMEFOLDER));
            if (useAppDataFolder) HighlightingManager.Manager.AddSyntaxModeFileProvider(new FileSyntaxModeProvider(System_AppData_FOLDER + "\\Highlighters\\"));

            app_settings.load_settings();
            Menu_File_New.Icon = Icons.@new;

            //Apply settings to this form
            app_applySettings();

            highlighterItems();

            app_SetSettings();

            if (!LiteVersion) UpdateControls((app_settings.icons != "default")); //Update all control text (and icons if true)

            //Add Recent Menu Controls
            app_settings.addControls(Menu_File_Recent);
            for (int i = 0; i < app_settings.recent.Length; i++)
            {
                app_settings.recent[i].Click += new EventHandler(handler_openRecent);
            }

            //Apply visual order to toolbars
            for (int i = app_settings.toolbars.Count - 1; i >= 0; i--)
            {
                ((Toolbar)app_settings.toolbars[i]).nToolbar.SendToBack();
            }
            Menu_.SendToBack();


            //Drag & Drop handlers
            Panel.DragEnter += new System.Windows.Forms.DragEventHandler(handler_textboxDrop);
            this.DragEnter += new System.Windows.Forms.DragEventHandler(handler_textboxDrop);

            Panel.DragDrop += new System.Windows.Forms.DragEventHandler(handler_textboxDrag);
            this.DragDrop += new System.Windows.Forms.DragEventHandler(handler_textboxDrag);

            if (this.Args != null)
            {
                ProcessParameters(null, this.Args);
                this.Args = null;
            }

            handler_Ifilewatcher_changed = new LoadFileDelegate(system_filewatcher_reload);

            handler_PanelTabChanged(null, null);

            if (DocumentTypes.getTypes.Count == 0) { trace("Error there are no document types defined !"); }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);
        }

        void DocumentTypes_Added(object sender, EventArgs e) {
           if (DocumentTypes.getTypes.Count > 1) {
               int start=DocumentTypes.getTypes.Count-1;
               if (DocumentTypes.getTypes.Count == 2) {
                   start--;
                //   Menu_File_New.Click -= new EventHandler(handler_new);
                //    Menu_File_Open.Click -= new EventHandler(handler_open);
               }
               for(int i = start ; i<DocumentTypes.getTypes.Count ; i++){
                   MenuItemX newItem = new MenuItemX();
                    newItem.Icon = Icons.@new;
                    newItem.Tag = i;
                    newItem.Text = DocumentTypes.getNames()[i];
                    newItem.Name = "Menu_File_New_" + newItem.Text;
                    newItem.Click +=new EventHandler(newItem_Click);
                    Menu_File_New.DropDownItems.Add(newItem);

                    MenuItemX openItem = new MenuItemX();
                    openItem.Icon = Icons.open;
                    openItem.Tag = i;
                    openItem.Text = DocumentTypes.getNames()[i];
                    newItem.Name = "Menu_File_Open_" + openItem.Text;
                    openItem.Click += new EventHandler(openItem_Click);
                    Menu_File_Open.DropDownItems.Add(openItem);
                }
            }
        }

        void openItem_Click(object sender, EventArgs e) {
            system_openBrowse((int)((ToolStripMenuItem)sender).Tag);
        }

        void newItem_Click(object sender, EventArgs e) {
            system_new((int)((ToolStripMenuItem)sender).Tag);
        }

        void Main_DocumentEvent(Notepad_X.Classes.Event.DocumentEvent e) { }

        /// <summary>
        /// Update the text and icons for all the controls
        /// </summary>
        /// <param name="UpdateIcons">Update icons or not</param>
        public void UpdateControls(Boolean UpdateIcons)
        {
            Components.Static.UpdateFormControls(this, UpdateIcons);
            Components.Static.UpdateContextMenuStrip(Menu_Context, UpdateIcons);
            Components.Static.UpdateContextMenuStrip(Menu_Content, UpdateIcons);

            //Update tab page icons if needed
            if (UpdateIcons)
            {
                foreach (TabPage tab in Panel.TabPages)
                {
                    if (tab.GetType() == typeof(TabPageX))
                    {
                        if (Documents[((TabPageX)tab).id].saved)
                        {
                            tab.ImageKey = "documentok";
                        }
                        else
                        {
                            tab.ImageKey = "documentchanged";
                        }
                    }

                }
            }
        }

        /// <summary>
        /// Reloads the highlighters buttons located at Menu_Tools_Highlight
        /// </summary>
        public void highlighterItems()
        {
            string key;
            HighlightingManager.Manager.ReloadSyntaxModes();

            if (Menu_Tools_Highlight.DropDownItems.Count > 2)
            {
                for (int i = Menu_Tools_Highlight.DropDownItems.Count - 1; i > -1; i--)
                {
                    ToolStripItem item = Menu_Tools_Highlight.DropDownItems[i];
                    if ((item.Name.ToLower() != "menu_tools_highlight_spectator") && (item.Name.ToLower() != "menu_tools_highlight_default"))
                    {
                        Menu_Tools_Highlight.DropDownItems.Remove(item);
                    }
                }
            }
            foreach (System.Collections.DictionaryEntry item in HighlightingManager.Manager.HighlightingDefinitions)
            {
                key = item.Key.ToString();
                if (key.ToLower() != "default")
                {
                    ToolStripMenuItem MenuItem = new ToolStripMenuItem();
                    MenuItem.Text = key;
                    MenuItem.Tag = key;
                    MenuItem.Name = "Menu_Tools_Hightlight_" + key;
                    Menu_Tools_Highlight.DropDownItems.Add(MenuItem);
                    MenuItem.Click += new EventHandler(handler_highlight);
                }
            }
        }

        #region AppFunctions
        /// <summary>
        /// Returns the index for an available empty tab
        /// </summary>
        private int app_getdocument(int typeIndex = -1) {
            if (typeIndex == -1) typeIndex = app_settings.defaultDocumentType;
            int i = 0;
            bool found = false;
            while ((!found) && (i < Documents.Count - 1)){
                if ((Documents[i] == null) || (Documents[i].available)){
                    Documents[i] = DocumentTypes.CreateDocument(typeIndex, i);// new ICshartDocument(i);
                    return i;
                }else{
                    i++;
                }
            }

            if (!found) return Documents.Add(DocumentTypes.CreateDocument(typeIndex, Documents.Count));
    
            return i;
        }

        /// <summary>
        /// Apply settings function
        /// </summary>
        private void app_applySettings()
        {
            this.Location = new Point(app_settings.location[0], app_settings.location[1]);
            this.Width = app_settings.size[0];
            this.Height = app_settings.size[1];

            Menu_Tools_LineNumbers.Checked = app_settings.line_numbers;

            if ((app_settings.language.ToLower() == "en") || (app_settings.language.ToLower() == null) || (app_settings.language.ToLower() == "english")) {
                app_settings.language = "english";
            }else{

                if (System.IO.File.Exists(System_ROOT + "\\translations\\" + app_settings.language) && !LiteVersion){
                    app_language.ReadLanguageFile(System_ROOT + "\\translations\\" + app_settings.language);
                }else if (System.IO.File.Exists(app_settings.language) && !LiteVersion){
                    app_language.ReadLanguageFile(app_settings.language);
                }else{
                    app_settings.language = "english";
                }

            }
        }
        public void app_SetSettings()
        {
            if (app_settings.status_bar){
                StatusBar.Visible = true;
            }else{
                StatusBar.Visible = false;
            }
            Background_Color = SystemColors.Window;
            Text_Color = SystemColors.WindowText;

            if (app_settings.BackgroundColor != null) {
                if ((Background_Color = Settings.ParseColor(app_settings.BackgroundColor)) == Color.Empty) { Background_Color = SystemColors.Window; app_settings.BackgroundColor = null; }
            }

            if (app_settings.TextColor != null){
                if ((Text_Color = Settings.ParseColor(app_settings.TextColor)) == Color.Empty) { Text_Color = SystemColors.WindowText; app_settings.TextColor = null; }
            }
            if (app_settings.defaultDocumentType > DocumentTypes.getTypes.Count) app_settings.defaultDocumentType = 0;
            Menu_Tools_Favourites.Visible = !LiteVersion;
        }

        #region System Functions

        /// <summary>
        /// Returns the selected document index if no tab selected returns -1
        /// </summary>
        public int get_selectedID()
        {
            int id = -1;
            if (Panel.TabCount > 0) {
                if (Panel.SelectedTab.GetType() != typeof(TabPageX)) {
                    return -1;
                }

                if (selectedTabContext ){
                    if (Panel.TabPages[selectedTabIndex].GetType() != typeof(TabPageX)) selectedTabContext = false;
                    else {
                        selectedTabContext = false;
                        return ((TabPageX)Panel.TabPages[selectedTabIndex]).id;
                    }
                } else{
                    if (Panel.SelectedTab.GetType() == typeof(TabPageX))
                    {
                        return  ((TabPageX)Panel.SelectedTab).id;
                    }
                }
            }
            return id;
        }
        /// <summary>
        /// Creates new Document and returns the document index
        /// </summary>
        private int system_new(int typeIndex = -1) {
            if (typeIndex == -1) typeIndex = app_settings.defaultDocumentType;
            int id = app_getdocument(typeIndex);
           // Console.WriteLine(id);
           //Documents[id] = new ICshartDocument(id);

           //Not needed Documents[id].DocumentChanged += new DocumentXEventHandler(handler_textboxChanged);
            //Documents[id].text_box.ActiveTextAreaControl.TextArea.DragDrop += new System.Windows.Forms.DragEventHandler(handler_textboxDrop);
            //Documents[id].text_box.ActiveTextAreaControl.Caret.PositionChanged += new System.EventHandler(handler_updateStatusBar);
            Documents[id].lineNumbers(app_settings.line_numbers);
            Documents[id].setColors(Background_Color, ForeColor);
            Documents[id].font = app_settings.font;
            ((Control)Documents[id].text_box).ContextMenuStrip = Menu_Content;
    
            Panel.TabPages.Add(Documents[id].tab_page);
            Documents[id].tab_page.DragDrop += new System.Windows.Forms.DragEventHandler(handler_textboxDrag);

            Documents[id].tab_page.ImageKey = "documentok";
            Documents[id].tab_page.Text = app_language[Strings.Document] + " " + (id + 1).ToString();
            Panel.SelectTab(Documents[id].tab_page);
            handler_PanelTabChanged(null, null);

            //Document Event 
            DocumentEvent(new Classes.Event.DocumentEvent(id, Notepad_X.Classes.Event.DocumentEvents.New));

            return id;
        }
        /// <summary>
        /// Saves current document to a file
        /// </summary>
        /// <param name="path">Path of the file</param>
        private void system_savefile(String path, int id)
        {
            if (id != -1)
            {
                if (Documents[id].watcher != null)
                {
                    Documents[id].watcher.Changed -= new System.IO.FileSystemEventHandler(handler_filewatcher_changed);
                    Documents[id].watcher = null;
                }
                Boolean ReadOnly = false;

                if (System.IO.File.Exists(path) && (System.IO.File.GetAttributes(path) == System.IO.FileAttributes.ReadOnly))
                {
                    System.IO.File.SetAttributes(path, System.IO.FileAttributes.Normal);
                    ReadOnly = true;
                }
                try
                {
                    Documents[id].save(path);
                   //Documents[id].text_box.Document.DocumentChanged += new ICSharpCode.TextEditor.Document.DocumentEventHandler(handler_textboxChanged);
                    Documents[id].tab_page.Text = System.IO.Path.GetFileName(path);
                    handler_PanelTabChanged(null, null);

                    //Document Event 
                    DocumentEvent(new Classes.Event.DocumentEvent(id, Notepad_X.Classes.Event.DocumentEvents.Save));

                }
                catch (System.IO.IOException e)
                {
                    MessageBox.Show(e.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                if (ReadOnly)
                {
                    System.IO.File.SetAttributes(path, System.IO.FileAttributes.ReadOnly);
                }
                //system_filewatcher(id);
            }
        }

        /// <summary>
        /// Saves current document
        /// </summary>
        private void system_save()
        {
            int id = get_selectedID();
            if (id != -1)
            {
                if (Documents[id].path == null)
                {
                    String dialog_path = system_saveDialog(Documents[id].tab_page.Text, id);
                    if (dialog_path != null)
                    {
                        system_savefile(dialog_path, id);
                    }
                }
                else
                {
                    system_savefile(Documents[id].path, id);
                }
                //Documents[id].text_box.Document.HighlightingStrategy = HighlightingManager.Manager.FindHighlighterForFile(Documents[id].path);
                app_settings.recent_add(Documents[id].path);
            }
        }

        /// <summary>
        /// Save as current document function
        /// </summary>
        private void system_saveAs()
        {
            int id = get_selectedID();
            if (id != -1)
            {
                String dialog_path = system_saveDialog(Documents[id].tab_page.Text, id);
                if (dialog_path != null)
                {
                    system_savefile(dialog_path, id);
                    //Documents[id].text_box.Document.HighlightingStrategy = HighlightingManager.Manager.FindHighlighterForFile(dialog_path);
                }
            }

        }
        /// <summary>
        /// Returns a file path for saving a new document
        /// </summary>
        private String system_saveDialog(String name, int id)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Title = app_language[Strings.Save];
            dialog.FileName = name;
            try
            {
                dialog.Filter = app_settings.extension_save;
            }
            catch { }
            if (id != -1)
            {
                if ((Documents[id].saved) && (Documents[id].path != null))
                {
                    dialog.InitialDirectory = System.IO.Path.GetFullPath(Documents[id].path);
                }
            }
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                return dialog.FileName;
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// Close current document
        /// </summary>
        private bool system_close()
        {
            bool ret = true;
            if (Panel.TabPages.Count != 0){
                int id = get_selectedID();
                if (id != -1) {
                    if (!Documents[id].saved){
                        DialogResult Result = MessageBox.Show("Do you want to save before closing", Documents[id].tab_page.Text, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                        if (Result == DialogResult.Yes) {
                            system_save();
                            if (Documents[id].watcher != null){
                                Documents[id].watcher.Changed -= new System.IO.FileSystemEventHandler(handler_filewatcher_changed);
                            }
                            Documents[id].clear();
                            Documents[id] = null;
                        }
                        else if (Result == DialogResult.No) {
                            if (Documents[id].watcher != null){
                                Documents[id].watcher.Changed -= new System.IO.FileSystemEventHandler(handler_filewatcher_changed);
                            }
                            Documents[id].clear();
                            Documents[id] = null;
                        }
                        else if (Result == DialogResult.Cancel){
                            ret = false;
                        }
                    }else{
                        if (Documents[id].watcher != null){
                            Documents[id].watcher.Changed -= new System.IO.FileSystemEventHandler(handler_filewatcher_changed);
                        }
                        Documents[id].clear();
                        Documents[id] = null;
                    }

                    //Document Event 
                    if (!ret){
                        DocumentEvent(new Classes.Event.DocumentEvent(id, Notepad_X.Classes.Event.DocumentEvents.Close));
                    }
                }else{
                    Panel.TabPages.Remove(Panel.SelectedTab);
                    //Panel.SelectedTab.Dispose();
                }
            }
            return ret;
        }

        /// <summary>
        /// Close all documents function
        /// </summary>
        private void system_closeAll()
        {
            int i = Panel.TabCount;
            while (i > 0)
            {
                if (i >= 1)
                {
                    Panel.SelectedIndex = i - 1;
                }
                system_close();
                i = i - 1;
            }
        }
        /// <summary>
        /// Close others function, it close all the tabs exept the selected
        /// </summary>
        private void system_closeOthers()
        {
            int id = get_selectedID();
            if (id != -1 && Panel.TabCount > 1)
            {
                TabPageX SelectedTab = (TabPageX)Panel.GetTabPageByID(id);
                if (SelectedTab != null)
                {
                    for (int i = Panel.TabCount; i > 0; i--)
                    {
                        Panel.SelectedIndex = i - 1;
                        if (Panel.SelectedTab != SelectedTab)
                        {
                            system_close();
                        }
                    }
                }
            }
        }
        public void system_openBrowse(int typeIndex = -1) {
            if (typeIndex == -1) typeIndex = app_settings.defaultDocumentType;
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Title = app_language[Strings.Open];
            dialog.Multiselect = true;
            try {
                if (!app_settings.extension_open.Contains("*.*"))
                    app_settings.extension_open = "All files (*.*)|*.*|" + app_settings.extension_open;

                dialog.Filter = app_settings.extension_open;
            } catch { }

            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
                foreach (var file in dialog.FileNames) {
                    system_open(file,typeIndex);
                }
            }
        }
        /// <summary>
        /// Open new file document
        /// </summary>
        /// <param name="path">Path of the file</param>
        public void system_open(String path, int typeIndex = -1 ) {
            if (typeIndex == -1) typeIndex = app_settings.defaultDocumentType;
            int id = get_selectedID();
            if (!((id != -1) && (String.IsNullOrEmpty(Panel.SelectedTab.Controls[0].Text))))
            {
                id = system_new(typeIndex);
            }

            Documents[id].open(path);
            //Documents[id].text_box.Document.DocumentChanged += new ICSharpCode.TextEditor.Document.DocumentEventHandler(handler_textboxChanged);
            app_settings.recent_add(path);
            Panel.SelectedTab.Text = System.IO.Path.GetFileName(path);

            system_filewatcher(id);

            //Document Event 
            DocumentEvent(new Classes.Event.DocumentEvent(id, Notepad_X.Classes.Event.DocumentEvents.Open));

            handler_PanelTabChanged(null, null);
        }
        public void system_filewatcher(int id)
        {
            if (id != -1 && !LiteVersion)
            {
                if ((Documents[id].saved) && (Documents[id].path != null))
                {
                    if (Documents[id].watcher != null)
                    {
                        Documents[id].watcher.Changed -= new System.IO.FileSystemEventHandler(handler_filewatcher_changed);
                        Documents[id].watcher = null;
                    }
                }
                Documents[id].watcher = new System.IO.FileSystemWatcher(System.IO.Path.GetDirectoryName(Documents[id].path), System.IO.Path.GetFileName(Documents[id].path));
                Documents[id].watcher.EnableRaisingEvents = true;

                Documents[id].watcher.Changed += new System.IO.FileSystemEventHandler(handler_filewatcher_changed);
            }
        }

        private void system_changeHightlight(String name)
        {
            int id = get_selectedID();
            if (id != -1)
            {
                //IC Sharp
                ((ICSharpCode.TextEditor.TextEditorControl)Documents[id].text_box).Document.HighlightingStrategy = ICSharpCode.TextEditor.Document.HighlightingManager.Manager.FindHighlighter(name);
            }
        }
        private void system_cut()
        {
            int id = get_selectedID();
            if (id != -1)
            {
                Documents[id].cut();
            }

        }
        private void system_copy()
        {
            int id = get_selectedID();
            if (id != -1)
            {
                Documents[id].copy();
            }
        }
        private void system_paste()
        {
            int id = get_selectedID();
            if (id != -1)
            {
                Documents[id].paste();
            }
        }
        private void system_pasteFormated()
        {
            //  int id = int.Parse(Panel.SelectedTab.Tag.ToString());
            //  Documents[id].text_box.ActiveTextAreaControl.TextArea.ClipboardHandler(null, null);
        }
        private void system_selectAll()
        {
            int id = get_selectedID();
            if (id != -1)
            {
                Documents[id].selectAll();
            }
        }
        private void system_undo()
        {
            int id = get_selectedID();
            if (id != -1)
            {
                Documents[id].undo();
            }
        }
        private void system_redo()
        {
            int id = get_selectedID();
            if (id != -1)
            {
                Documents[id].redo();
            }
        }
        private void system_favourite()
        {
            int id = get_selectedID();
            if (id != -1)
            {
                if (!String.IsNullOrEmpty(Documents[id].path))
                {
                    if (app_settings.favourite_add(Documents[id].path))
                    {
                        //show added
                    }
                    else
                    { };//already exist
                }
            }
        }
        private bool system_find(System.Text.RegularExpressions.Regex reg, bool searchUp)
        {
            int id = get_selectedID();
            if (id != -1) {
                Documents[id].find(Find_Text.Text);
            }
            return false;
        }
 
        public void system_replace(System.Text.RegularExpressions.Regex reg, bool searchUp)
        {
            int id = get_selectedID();
            if (id != -1) {
                Documents[id].replace(Find_Text.Text,Find_Replace.Text);
            }
        }

        private void system_checkHighlighter()
        {
            int id = get_selectedID();
            if (id != -1 && Documents[id] != null)
            {
                TextEditorControl TextBox;
                // IF ICSharp
                if (Documents[id].GetType() == typeof(ICshartDocument)) {
                    TextBox = (TextEditorControl)Documents[id].text_box;
                } else {
                    return;
                }
                string highlighter = TextBox.Document.HighlightingStrategy.Name.ToLower();
                for (int i = 0; i < Menu_Tools_Highlight.DropDownItems.Count; i++)
                {
                    if ((Menu_Tools_Highlight.DropDownItems[i].GetType() == typeof(ToolStripMenuItem)) || (Menu_Tools_Highlight.DropDownItems[i].GetType() == typeof(MenuItemX)))
                    {
                        if (Menu_Tools_Highlight.DropDownItems[i].Text.ToLower() == highlighter)
                        {
                            ((ToolStripMenuItem)Menu_Tools_Highlight.DropDownItems[i]).Checked = true;
                        }
                        else
                        {
                            ((ToolStripMenuItem)Menu_Tools_Highlight.DropDownItems[i]).Checked = false;
                        }
                        if (highlighter == "default") //ToLower())
                        {
                            Menu_Tools_Highlight_Default.Checked = true;
                        }
                    }
                }
            }

        }
        private void system_filewatcher_reload()
        {
            int id = get_selectedID();
            if (id != -1)
            {
                if (!Documents[id].watcherChanged)
                {
                    DialogResult result = MessageBox.Show("Document has changed, do you want to reload ?", Panel.SelectedTab.Text, MessageBoxButtons.YesNo);
                    if (result == DialogResult.Yes)
                    {

                        Documents[id].watcher.Changed -= new System.IO.FileSystemEventHandler(handler_filewatcher_changed);
                        Documents[id].watcherChanged = true;
                        //Reload
                        Documents[id].open(Documents[id].path);
                        //Documents[id].set_saved();
                        //Documents[id].text_box.Document.DocumentChanged += new ICSharpCode.TextEditor.Document.DocumentEventHandler(handler_textboxChanged);
                        app_settings.recent_add(Documents[id].path);
                        system_filewatcher(id);
                        Documents[id].watcherChanged = false;

                    }
                    else if (result == DialogResult.No)
                    {
                        Documents[id].watcherChanged = true;
                    }

                    //}else{ dont notify the user
                }
            }
        }
        #endregion

        /// <summary>
        /// Search an ToolStripMenuItem located at Menu_ by it's name and returns it
        /// </summary>
        /// <param name="name">ToolStripMenuItem control name</param>
        public ToolStripMenuItem system_menuItem_Get(string name)
        {
            //Smart Search
            if (name.Contains("_"))
            {
                String[] values = name.Split('_');
                if (values.Length == 2)
                {
                    if (Menu_.Items.ContainsKey(name))
                    {
                        return (ToolStripMenuItem)Menu_.Items[name];
                    }
                }
                else if (values.Length == 3)
                {
                    if (Menu_.Items.ContainsKey(values[0] + "_" + values[1]))
                    {
                        ToolStripMenuItem parent = (ToolStripMenuItem)Menu_.Items[values[0] + "_" + values[1]];
                        if (parent.DropDownItems.ContainsKey(name))
                        {
                            return (ToolStripMenuItem)parent.DropDownItems[name];
                        }
                    }
                }
                else if (values.Length == 4)
                {
                    if (Menu_.Items.ContainsKey(values[0] + "_" + values[1]))
                    {
                        ToolStripMenuItem parent = (ToolStripMenuItem)Menu_.Items[values[0] + "_" + values[1]];
                        if (parent.DropDownItems.ContainsKey(values[0] + "_" + values[1] + "_" + values[2]))
                        {
                            parent = (ToolStripMenuItem)parent.DropDownItems[values[0] + "_" + values[1] + "_" + values[2]];
                            if (parent.DropDownItems.ContainsKey(name))
                            {
                                return (ToolStripMenuItem)parent.DropDownItems[name];
                            }
                        }
                    }
                }
            }
            //If Smart Search fails use the traditional way

            name = name.ToLower();

            foreach (ToolStripItem item in Menu_.Items)
            {
                if ((item.GetType() == typeof(ToolStripMenuItem)) || (item.GetType() == typeof(MenuItemX)))
                {
                    if (item.Name.ToLower() == name)
                    {
                        return (ToolStripMenuItem)item;
                    }
                    else
                    {
                        foreach (ToolStripItem subitem in ((ToolStripMenuItem)item).DropDownItems)
                        {
                            if ((subitem.GetType() == typeof(ToolStripMenuItem)) || (subitem.GetType() == typeof(MenuItemX)))
                            {
                                if (subitem.Name.ToLower() == name)
                                {
                                    return (ToolStripMenuItem)subitem;
                                }
                                else
                                {
                                    foreach (ToolStripItem sub2item in ((ToolStripMenuItem)subitem).DropDownItems)
                                    {
                                        if ((sub2item.GetType() == typeof(ToolStripMenuItem)) || (sub2item.GetType() == typeof(MenuItemX)))
                                        {
                                            if (sub2item.Name.ToLower() == name)
                                            {
                                                return (ToolStripMenuItem)sub2item;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //If dont find any
            return null;
        }
        #endregion

        #region Handlers
        // Handlers
        public void handler_textboxDrag(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
            {
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
                foreach (string file in files)
                {
                    system_open(file);
                }
            }
        }
        private void handler_textboxDrop(object sender, DragEventArgs e)
        {
            //if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
            //{
            e.Effect = DragDropEffects.All;
            //}
        }

        /// <summary>
        /// Handler for system_save function
        /// </summary>
        public void handler_save(object sender, EventArgs e)
        {
            system_save();
        }
        /// <summary>
        /// Handler for system_saveAs function
        /// </summary>
        public void handler_saveAs(object sender, EventArgs e)
        {
            system_saveAs();
        }
        /// <summary>
        /// Handler for system_close function
        /// </summary>
        public void handler_close(object sender, EventArgs e)
        {
            system_close();
        }
        /// <summary>
        /// Handler for system_new function
        /// </summary>
        public void handler_new(object sender, EventArgs e)
        {
            system_new();
        }
        /// <summary>
        /// Handler for system_closeAll function
        /// </summary>
        public void handler_closeAll(object sender, EventArgs e)
        {
            system_closeAll();
        }
        /// <summary>
        /// Handler for system_closeOthers function
        /// </summary>
        public void handler_closeOthers(object sender, EventArgs e)
        {
            system_closeOthers();
        }
        public void handler_open(object sender, EventArgs e)
        {
            system_openBrowse();
        }
        /// <summary>
        /// Handler for system_copy function
        /// </summary>
        public void handler_copy(object sender, EventArgs e)
        {
            system_copy();
        }
        public void handler_cut(object sender, EventArgs e)
        {
            system_cut();
        }
        public void handler_paste(object sender, EventArgs e)
        {
            system_paste();
        }
        public void handler_pasteFormated(object sender, EventArgs e)
        {

        }
        public void handler_selectAll(object sender, EventArgs e)
        {
            system_selectAll();
        }
        public void handler_undo(object sender, EventArgs e)
        {
            system_undo();
        }
        public void handler_redo(object sender, EventArgs e)
        {
            system_redo();
        }
        public void handler_favourite(object sender, EventArgs e)
        {
            system_favourite();
        }
        public void handler_find(object sender, EventArgs e)
        {
            Find_.Visible = true;
            Find_Text.Focus();
            Find_Text.SelectAll();
            Find_ReplaceCheck.Checked = true;
            handler_find_replaceCheck(null, null);
        }
        public void handler_replace(object sender, EventArgs e)
        {
            Find_.Visible = true;
            Find_Text.Focus();
            Find_Text.SelectAll();
            Find_ReplaceCheck.Checked = false;
            handler_find_replaceCheck(null, null);
        }
        public void handler_goto(object sender, EventArgs e)
        {
            GoTo_.Visible = true;
            GoTo_Value.Focus();
            GoTo_Value.SelectAll();
        }

        public void handler_rename(object sender, EventArgs e)
        {
            Rename_.Visible = true;
            Rename_Name.Text = Panel.SelectedTab.Text;
            Rename_Name.Focus();
        }
        public void handler_highlight(object sender, EventArgs e)
        {
            ToolStripMenuItem item = (ToolStripMenuItem)sender;
            system_changeHightlight(item.Tag.ToString());
            system_checkHighlighter();
        }
        public void handler_print(object sender, EventArgs e)
        {
            int id = get_selectedID();
            if (id != -1)
            {
                PrintDialog printDialog = new PrintDialog();
                printDialog.Document = Documents[id].printDocument;
                printDialog.UseEXDialog = true;
                if (printDialog.ShowDialog() == DialogResult.OK)
                {
                    printDialog.Document.Print();
                }
                
            }
        }
        public void handler_printPreview(object sender, EventArgs e)
        {
            int id = get_selectedID();
            if (id != -1)
            {
                PrintPreviewDialog previewDialog = new PrintPreviewDialog();
                previewDialog.Document = Documents[id].printDocument;
                previewDialog.ShowDialog();
            }
        }
        public void handler_pageSetup(object sender, EventArgs e)
        {
            int id = get_selectedID();
            if (id != -1)
            {
                PageSetupDialog pageSetup = new PageSetupDialog();
                pageSetup.Document = Documents[id].printDocument;
                pageSetup.ShowDialog();
            }
        }
        public void handler_openRecent(object sender, EventArgs e)
        {
            system_open(((RecentMenuItemX)sender).path);
        }

        public void handler_lineNumbers(object sender, EventArgs e)
        {
            app_settings.line_numbers = Menu_Tools_LineNumbers.Checked = (!app_settings.line_numbers);
            for (int i = 0; i < Documents.Count; i++)
            {
                if (Documents[i] != null)
                    Documents[i].lineNumbers(app_settings.line_numbers);
            }
        }

        private void handler_PanelMouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                Point pt = new Point(e.X, e.Y);
                Notepad_X.Components.TabPageX tp = Panel.GetTabPageByTab(pt);

                if (tp != null)
                {
                    selectedTabIndex = Panel.TabPages.IndexOf(tp);
                }
                else
                {
                    selectedTabIndex = Panel.SelectedIndex;
                }
            }
        }

        public void handler_PanelTabChanged(object sender, EventArgs e)
        {
            bool enabled = true;
            string NotepadX = "Notepad X v2";
            if (LiteVersion) { NotepadX = "Notepad X v2 (Lite)"; }

            if (Panel.SelectedTab != null)
            {
                this.Text = Panel.SelectedTab.Text + " - " + NotepadX;
            }
            else
            {
                this.Text = NotepadX;
                enabled = false;
            }

            system_checkHighlighter();

            if (Menu_File_Save.Enabled != enabled)
            {

                Menu_File_Save.Enabled = enabled;
                Menu_File_SaveAs.Enabled = enabled;
                Menu_File_Close.Enabled = enabled;
                Menu_File_Print.Enabled = enabled;
                Menu_File_PrintPreview.Enabled = enabled;
                Menu_File_PageSetup.Enabled = enabled;
                Menu_File_Print.Enabled = enabled;

                Menu_Edit_Undo.Enabled = enabled;
                Menu_Edit_Redo.Enabled = enabled;
                Menu_Edit_Copy.Enabled = enabled;
                Menu_Edit_Cut.Enabled = enabled;
                Menu_Edit_Paste.Enabled = enabled;
                Menu_Edit_SelectAll.Enabled = enabled;
                Menu_Edit_Find.Enabled = enabled;
                Menu_Edit_Replace.Enabled = enabled;
                Menu_Edit_GoTo.Enabled = enabled;

                Menu_Tabs_Rename.Enabled = enabled;
                Menu_Tabs_Close.Enabled = enabled;
                Menu_Tabs_CloseAll.Enabled = enabled;
                Menu_Tabs_Previous.Enabled = enabled;
                Menu_Tabs_Next.Enabled = enabled;
                Menu_Tools_Favourites_Add.Enabled = enabled;
            }
        }
        public void handler_options(object sender, EventArgs e)
        {
            Options_Dialog.ShowDialog();
        }
        public void handler_help(object sender, EventArgs e)
        {
            try
            { System.Diagnostics.Process.Start("http://notepad-x.sourceforge.net/?page_id=15"); }
            catch (Exception){}
        }
        public void handler_website(object sender, EventArgs e)
        {
            try
            { System.Diagnostics.Process.Start("http://notepad-x.sourceforge.net"); }
            catch (Exception){}
        }
        public void handler_bugreport(object sender, EventArgs e)
        {
            try
            { System.Diagnostics.Process.Start("http://notepad-x.sourceforge.net/submit/bug-report"); }
            catch (Exception){}
        }
        public void handler_featurerequest(object sender, EventArgs e)
        {
            try
            { System.Diagnostics.Process.Start("http://notepad-x.sourceforge.net/?page_id=88&wpforumaction=viewforum&f=2.0"); }
            catch (Exception){}
        }
        public void handler_about(object sender, EventArgs e)
        {
            About_Dialog.ShowDialog();
        }

        public void handler_favouritesOrganize(object sender, EventArgs e)
        {
            Favourites_Dialog.ShowDialog();
        }

        private void handler_doubleclick_close(object sender, MouseEventArgs e)
        {
            handler_close(null, null);
        }
        public void handler_selectNext(object sender, EventArgs e)
        {
            if (Panel.TabCount - 1 < Panel.SelectedIndex + 1)
            {
                Panel.SelectedIndex = 0;
            }
            else
            {
                Panel.SelectedIndex = Panel.SelectedIndex + 1;
            }
        }

        public void handler_selectPrevious(object sender, EventArgs e)
        {
            if (Panel.SelectedIndex - 1 < 0)
            {
                Panel.SelectedIndex = Panel.TabCount - 1;
            }
            else
            {
                Panel.SelectedIndex = Panel.SelectedIndex - 1;
            }
        }

        public void handler_exit(object sender, EventArgs e)
        {
            this.Close();
        }
        public void handler_openFolder(object sender, EventArgs e)
        {
            int id = get_selectedID();
            if (id != -1)
            {
                if ((Documents[id].path != null) && System.IO.File.Exists(Documents[id].path))
                {
                    try {
                        System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(Documents[id].path));
                    } catch (Exception) { }
                }
            }
        }
        public void handler_tag(object sender, EventArgs e)
        {
          int id = get_selectedID();
          if (id != -1) {
              string[] tag = ((ToolStripItem)sender).Tag.ToString().Split('|');

   
              if (tag.Length == 1) {
                   Documents[id].insert(Documents[id].selectionIndex() , tag[0]);

              } else if (tag.Length == 2) {
                  Documents[id].insert(Documents[id].selectionIndex() , tag[0]);

                  Documents[id].insert(Documents[id].selectionIndex() + (Documents[id].selectedText() ==null ? 0 : Documents[id].selectedText().Length) + tag[0].Length, tag[1]);
              }
          }
        }

        // Private Handlers
        private LoadFileDelegate handler_Ifilewatcher_changed;

        private void handler_filewatcher_changed(object sender, EventArgs e)
        {
            Invoke(handler_Ifilewatcher_changed);
        }
        private void handler_recentClear(object sender, EventArgs e)
        {
            app_settings.recent_clear();
        }

        private void handler_find_close(object sender, EventArgs e)
        {
            Find_.Visible = false;
        }
        private void handler_FindEnterPressed(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                handler_findorreplace(null, null);
            }
        }
        private void handler_findorreplace(object sender, EventArgs e)
        {
            if (Find_ReplaceCheck.Checked)
            {
                system_replace(null, true);
            }
            else
            {
                system_find(null, true);
            }
        }
        private void handler_find_replaceCheck(object sender, EventArgs e)
        {
            if (Find_ReplaceCheck.Checked)
            {
                Find_ReplaceCheck.Checked = false;
                Find_Replace.Visible = false;
                Find_Find.Text = app_language[Strings.Find];
            }
            else
            {
                Find_ReplaceCheck.Checked = true;
                Find_Replace.Visible = true;
                Find_Find.Text = app_language[Strings.Replace];
            }
        }
        private void handler_rename_close(object sender, EventArgs e)
        {
            if (Panel.SelectedTab != null)
            {
                Panel.SelectedTab.Controls[0].Focus();
            }
            Rename_.Visible = false;
        }
        private void handler_goto_close(object sender, EventArgs e)
        {
            GoTo_.Visible = false;
        }
        private void handler_Rename_OK(object sender, EventArgs e)
        {
            if (Panel.SelectedTab != null)
            {
                Panel.SelectedTab.Text = Rename_Name.Text;
                Rename_.Visible = false;
                Panel.SelectedTab.Controls[0].Focus();
                handler_PanelTabChanged(null, null);
            }
        }
        private void GoTo_Go_Click(object sender, EventArgs e)
        {
            int id = get_selectedID();
            if (id != -1)
            {

                int line;
                if (int.TryParse(GoTo_Value.Text, out line))
                {
                    //TextBox.ActiveTextAreaControl.JumpTo(line - 1);
                    Documents[id].goTo(line);
                   ((Control)Documents[id].text_box).Focus();
                    GoTo_.Visible = false;
                    GoTo_Value.ForeColor = SystemColors.WindowText;
                }
                else
                {
                    GoTo_Value.ForeColor = Color.Red;
                }
            }
        }
        #endregion

        /// <summary>
        /// Show a message box
        /// </summary>
        /// <param name="str"></param>
        public void trace(String str)
        {
            MessageBox.Show(str);
        }

        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            int i = Panel.TabCount;
            while (i > 0)
            {
                if (i >= 1)
                {
                    Panel.SelectedIndex = i - 1;
                }
                if (!system_close())
                {
                    e.Cancel = true;
                    break;
                }
                i--;
            }
            if (!e.Cancel)
            {
                if (this.WindowState == FormWindowState.Maximized)
                {
                    this.WindowState = FormWindowState.Normal;
                }

                app_settings.location[0] = this.Location.X;
                app_settings.location[1] = this.Location.Y;

                app_settings.size[0] = this.Size.Width;
                app_settings.size[1] = this.Size.Height;

                app_settings.save_settings();

                Global.Plugins.ClosePlugins();
        
            }
        }
        private void Menu_Context_Opening(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Menu_Context_SelectedDocument.Text = Panel.TabPages[selectedTabIndex].Text;
        }
        private void Menu_Context_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            selectedTabContext = true;
        }

    }
    /// <summary>
    /// Link for other forms & plugins to Main Window
    /// </summary>
    public static class Static
    {
        public static Main MainInstance;
    }
}
